package controller

import (
	"errors"
	"github.com/labstack/echo"
	"github.com/qiniu/api.v7/v7/storage"
	uuid "github.com/satori/go.uuid"
	"github.com/sirupsen/logrus"
	"net/http"
	"src/config"
	"src/controller/param"
	"src/model"
	"src/util"
	"src/util/context"
	"src/util/log"
	"src/util/token"
	"strconv"
	"strings"
)

var indexLogger = log.GetLogger()

func writeindexLoggerLoggerLog(funcName, errMsg string, err error) {
	indexLogger.WithFields(logrus.Fields{
		"package":  config.LogMessage,
		"file":     "index.go",
		"function": funcName,
		"err":      err,
	}).Warn(errMsg)
}

func Login(c echo.Context) error {
	data := param.LoginData{}
	err := c.Bind(&data)
	if err != nil || data.Code == "" {
		writeindexLoggerLoggerLog("Login", config.ErrorMsgParamWrong, err)
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorMsgParamWrong)
	}

	authData, err := model.GetWeixinSession(data.Code)
	if err != nil {
		writeindexLoggerLoggerLog("Login", config.ErrorLogin, err)
		return context.RetError(c, http.StatusBadGateway, http.StatusBadGateway, config.ErrorLogin)
	}
	if authData.Errmsg != "" {
		writeindexLoggerLoggerLog("Login1", config.ErrorLogin, errors.New(strconv.Itoa(authData.Errcode)+" "+authData.Errmsg))
		return context.RetError(c, http.StatusBadGateway, http.StatusBadGateway, config.ErrorLogin+" "+strconv.Itoa(authData.Errcode)+" "+authData.Errmsg)
	}

	if authData.Openid == "" || authData.SessionKey == "" {
		writeindexLoggerLoggerLog("Login", "Has not OPenid && Session", err)
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorLogin)
	}
	writeindexLoggerLoggerLog("Login", "1:"+authData.Openid+" "+authData.SessionKey+" union:"+authData.Unionid, err)
	// 存储session_key
	err = model.SetWeixinSessionKey(authData.Openid, authData.Unionid)
	writeindexLoggerLoggerLog("Login", "2", err)
	if err != nil {
		writeindexLoggerLoggerLog("Login", "微信Session_key存储失败", err)
		return context.RetError(c, http.StatusBadGateway, http.StatusBadGateway, "微信Session_key存储失败")
	}

	var userInfo *util.DecryptUserInfo
	if authData.Unionid == "" {
		userInfo, err = model.DecryptWeixinEncryptedData(authData.SessionKey, data.EncryptedData, data.Iv)
		writeindexLoggerLoggerLog("Login", "3", err)
		if err != nil {
			writeindexLoggerLoggerLog("Login", config.ErrorMsgParamWrong, err)
			return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorMsgParamWrong)
		}
	} else {
		userInfo = &util.DecryptUserInfo{
			UnionID:   authData.Unionid,
			OpenID:    authData.Openid,
			NickName:  data.UserInfo.Nickname,
			Gender:    data.UserInfo.Gender,
			AvatarURL: data.UserInfo.AvatarURL,
		}
	}
	writeindexLoggerLoggerLog("Login", "4", err)
	_, err = model.GetUserInfo(authData.Openid)
	writeindexLoggerLoggerLog("Login", "5", err)
	if err != nil {
		err = model.CreatUser(authData, userInfo)
		writeindexLoggerLoggerLog("Login", "6", err)
		if err != nil {
			writeindexLoggerLoggerLog("Login", config.ErrorUserCreat, err)
			return context.RetError(c, http.StatusBadGateway, http.StatusBadGateway, config.ErrorUserCreat)
		}
	} else {
		if authData.Openid != "" && userInfo.AvatarURL != "" {
			err = model.ChangeUserImg(authData.Openid, userInfo)
			writeindexLoggerLoggerLog("Login", "7", err)
		}
	}

	jwtAuth := map[string]interface{}{
		"openid": authData.Openid,
	}

	jwtToken := token.GetJWTToken(jwtAuth)
	writeindexLoggerLoggerLog("Login", "8", err)
	// csrfToken := token.GetCSRFToken()

	resData := map[string]interface{}{
		"jwt_token": jwtToken,
		"openid":    authData.Openid,
		// "csrf_token":  csrfToken,
	}
	return context.RetData(c, resData)
}

func LoginTest(c echo.Context) error {
	data := param.LoginTest{}
	err := c.Bind(&data)
	if err != nil || data.Openid == "" {
		writeindexLoggerLoggerLog("LoginTest", config.ErrorMsgParamWrong, err)
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorMsgParamWrong)
	}
	if data.Secret != "87542701" {
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, "密码错误")
	}
	data.Openid = "123456"
	authData := model.WeixinSessRes{
		Openid:  data.Openid,
		Unionid: "123456",
	}
	usr := &util.DecryptUserInfo{}

	_, err = model.GetUserInfo(authData.Openid)
	if err != nil {
		err = model.CreatUser(authData, usr)
		if err != nil {
			writeindexLoggerLoggerLog("Login", config.ErrorUserCreat, err)
			return context.RetError(c, http.StatusBadGateway, http.StatusBadGateway, config.ErrorUserCreat)
		}
	}

	jwtAuth := map[string]interface{}{
		"openid": authData.Openid,
	}

	jwtToken := token.GetJWTToken(jwtAuth)
	// csrfToken := token.GetCSRFToken()

	resData := map[string]interface{}{
		"jwt_token": jwtToken,
		"openid":    authData.Openid,
		// "csrf_token":  csrfToken,
	}
	return context.RetData(c, resData)
}

func GetQiniuImgUpToken(c echo.Context) error {
	data := param.TypeParam{}
	err := c.Bind(&data)
	if err != nil {
		writeindexLoggerLoggerLog("GetQiniuImgUpToken", config.ErrorMsgParamWrong, err)
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorMsgParamWrong)
	}
	if data.Num < 1 {
		data.Num = 1
	}
	imgID := []string{}
	for i := 0; i < data.Num; i++ {
		a := uuid.NewV4().String()
		imgID = append(imgID, a)
	}

	suffix := data.Suffix
	if suffix == "" {
		suffix = config.ImgSuffix
	}

	imgPrefix, ok := config.ImgPrefix[data.Type]
	if !ok {
		writeindexLoggerLoggerLog("GetQiniuImgUpToken", config.ErrorMsgParamWrong, err)
		return context.RetError(c, http.StatusBadRequest, http.StatusBadRequest, config.ErrorMsgParamWrong)
	}
	microImgPrefix := config.ImgPrefixMicro[data.Type]

	RES := []param.Qiniu{}

	for i := 0; i < data.Num; i++ {
		keyToOverwrite := imgPrefix + imgID[i] + suffix
		saveAsKey := microImgPrefix + imgID[i] + suffix

		fop := config.ImgOps + "|saveas/" + storage.EncodedEntry(config.Conf.Qiniu.Bucket, saveAsKey)
		persistentOps := strings.Join([]string{fop}, ";")
		upToken := token.GetCustomUpToken(keyToOverwrite, persistentOps, config.TokenQiniuExpire)

		img := model.Img{
			URL:      config.ImgURIPrefix + keyToOverwrite,
			MicroURL: config.ImgURIPrefix + saveAsKey,
		}
		a := param.Qiniu{
			Upload_token: upToken,
			Key:          keyToOverwrite,
			Img:          img,
		}
		RES = append(RES, a)
	}
	resData := map[string]interface{}{}
	resData["QiniuUps"] = RES
	return context.RetData(c, resData)
}
